<template>
  <div class="form-single-fragment third-party-dlg" style="position: relative">
    <el-row class="script-editor-header" justify="space-between">
      <el-col :span="16">
        <div class="script-editor-tips">
          注：直接编写运行于后台的 Javascript 代码，使用 ${ } 可以插入参数，Ctrl + s 可以保存脚本。
        </div>
      </el-col>
      <el-col :span="8">
        <div class="script-editor-actions">
          <el-button :icon="Finished" @click="onFormat">格式化</el-button>
          <el-button :icon="VideoPlay" @click="onOpenRunDialog">模拟运行</el-button>
          <el-button :icon="Check" type="primary" @click="handleSaveScript">保存脚本</el-button>
        </div>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="24" style="height: 720px">
        <ScriptEditor
          ref="scriptEditor"
          v-model:value="scriptContent"
          style="width: 100%; height: 720px; border: 1px solid #dcdcdc"
          :title="'脚本内容'"
          :completer="scriptCompleter"
          @save="handleSaveScript"
        />
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { ElMessage } from 'element-plus';
import { Finished, VideoPlay, Check } from '@element-plus/icons-vue';
import ScriptEditor from '@/components/ScriptEditor/index.vue';
import { DialogProp } from '@/components/Dialog/types';
import { Dialog } from '@/components/Dialog';
import { ANY_OBJECT } from '@/types/generic';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { OnlineApi } from '@/types/online/script';
import OnlineApiController from '@/api/online/OnlineApiController';
import EditRunScript from './editRunScript.vue';

interface IProps extends ThirdProps {
  formData?: OnlineApi;
  onSaveScript?: (script: string) => void;
  // 当使用Dialog.show弹出组件时，须定义该prop属性，以便对dialog进行回调
  dialog?: DialogProp<ANY_OBJECT>;
}

const props = defineProps<IProps>();
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);

const scriptEditor = ref();
const scriptContent = ref('');
const scriptCompleter = ref<ANY_OBJECT>({});

const dialogParams = computed(() => {
  return {
    formData: props.formData || thirdParams.value.formData,
    onSaveScript: props.onSaveScript || thirdParams.value.onSaveScript,
  };
});

// 解析API参数配置
const apiParams = computed(() => {
  const extraData = dialogParams.value.formData?.extraData;
  if (!extraData) return [];
  try {
    return JSON.parse(extraData);
  } catch (e) {
    console.error('解析脚本参数配置失败:', e);
    return [];
  }
});

// 格式化脚本（暂时不行，要实现的话需要使用 js-beautify 库）
const onFormat = () => {
  try {
    scriptEditor.value.formatCode();
    ElMessage.success('格式化成功');
  } catch (e) {
    console.error(e);
    ElMessage.error('格式化失败');
  }
};

// 打开模拟运行弹窗
const onOpenRunDialog = () => {
  handleSaveScript();
  Dialog.show(
    '模拟运行脚本',
    EditRunScript,
    {
      area: ['800px', '710px'],
    },
    {
      rowData: dialogParams.value.formData,
    },
  ).catch(e => {
    console.warn(e);
  });
};

// 保存脚本
const handleSaveScript = () => {
  try {
    const runRowData = dialogParams.value.formData;
    OnlineApiController.update({
      onlineApiDto: {
        ...runRowData,
        apiScript: scriptContent.value,
      },
    })
      .then(res => {
        ElMessage.success('保存成功');
        if (dialogParams.value.onSaveScript) {
          dialogParams.value.onSaveScript(scriptContent.value);
        }
      })
      .catch(e => {
        console.error(e);
        ElMessage.error('保存失败');
      });
  } catch (e) {
    console.error(e);
    ElMessage.error('保存失败');
  }
};

onMounted(() => {
  if (dialogParams.value.formData) {
    scriptContent.value = dialogParams.value.formData.apiScript || '';
  }

  // 脚本编辑器的代码提示配置
  scriptCompleter.value = {
    triggerCharacters: ['${'],

    getCompletions: function (
      editor: ANY_OBJECT,
      session: ANY_OBJECT,
      pos: ANY_OBJECT,
      prefix: string,
      callback: ANY_OBJECT,
    ) {
      interface Completion {
        caption: string;
        value: string;
        meta: string;
        docText: string;
        type: string;
        score: number;
      }

      let completions: Completion[] = [];

      // 添加参数提示
      apiParams.value.forEach((param: ANY_OBJECT, index: number) => {
        completions.push({
          caption: `\${${param.paramName}}`,
          value: `\${${param.paramName}}`,
          meta: param.paramType,
          docText: param.paramDesc || param.paramName,
          type: 'parameter',
          score: 100 - index,
        });
      });

      callback(null, completions);
    },
  };
});
</script>

<style scoped>
.script-editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 20px;
}

.script-editor-tips {
  color: #909399;
  font-size: 14px;
}

.script-editor-actions {
  display: flex;
  justify-content: flex-end;
  gap: 5px;
}

.script-editor-actions .el-button {
  display: flex;
  align-items: center;
  gap: 4px;
}
</style>
